x86: Detect shadow-emulate write to stack from inside the write
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 22 Feb 2007 15:22:16 +0000 (15:22 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 22 Feb 2007 15:22:16 +0000 (15:22 +0000)
handler, where we can quite conveniently check whether the access
segment is SS. This will only give a false positive for non-stack
writes that override the destination segment to SS, which it is
probably safe to assume will never happen when the destination is a
legitimate page table!

For now, instead of bailing and unshadowing just increment a perfctr
and we'll see if that increases fast under any reasonable workload.

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/mm/shadow/common.c
xen/arch/x86/mm/shadow/multi.c
xen/include/asm-x86/perfc_defn.h

index f74d18a3c621f09937cb732ccd9b52bbb02e4538..e3b4821010798dbb6c6db5700eb77fe461c5db3d 100644 (file)
@@ -275,6 +275,10 @@ hvm_emulate_write(enum x86_segment seg,
     unsigned long addr;
     int rc;
 
+    /* How many emulations could we save if we unshadowed on stack writes? */
+    if ( seg == x86_seg_ss )
+        perfc_incrc(shadow_fault_emulate_stack);
+
     rc = hvm_translate_linear_addr(
         seg, offset, bytes, hvm_access_write, sh_ctxt, &addr);
     if ( rc )
index e348bebaa627f109ac732e443c6a324c277055ee..a1748058f9ee1f267d287704a49bbc6d9f9b3080 100644 (file)
@@ -2924,23 +2924,6 @@ static int sh_page_fault(struct vcpu *v,
     SHADOW_PRINTK("emulate: eip=%#lx esp=%#lx\n", 
                   (unsigned long)regs->eip, (unsigned long)regs->esp);
 
-    /*
-     * Check whether this looks like a stack operation. If so, unshadow the
-     * faulting page. We can allow this to fail: if it does fail then we
-     * carry on and emulate, otherwise we bail immediately. Failure is
-     * tolerated because this is only a heuristic (e.g., stack segment base
-     * address is ignored).
-     */
-    if ( unlikely((va & PAGE_MASK) == (regs->esp & PAGE_MASK)) )
-    {
-        gdprintk(XENLOG_DEBUG, "guest stack is on a shadowed frame: "
-                 "%%esp=%#lx, cr2=%#lx, mfn=%#lx\n", 
-                 (unsigned long)regs->esp, va, mfn_x(gmfn));
-        sh_remove_shadows(v, gmfn, 0 /* thorough */, 0 /* can fail */);
-        if ( !(mfn_to_page(gmfn)->count_info & PGC_page_table) )
-            goto done;
-    }
-
     emul_ops = shadow_init_emulation(&emul_ctxt, regs);
 
     /*
index ba1e32c8fd580433fddb04f612f9e8d705bcbea0..054fa0f1af38a6735ff489132acd360f0550187f 100644 (file)
@@ -56,6 +56,7 @@ PERFCOUNTER_CPU(shadow_fault_bail_user_supervisor,
 PERFCOUNTER_CPU(shadow_fault_emulate_read, "shadow_fault emulates a read")
 PERFCOUNTER_CPU(shadow_fault_emulate_write, "shadow_fault emulates a write")
 PERFCOUNTER_CPU(shadow_fault_emulate_failed, "shadow_fault emulator fails")
+PERFCOUNTER_CPU(shadow_fault_emulate_stack, "shadow_fault emulate stack write")
 PERFCOUNTER_CPU(shadow_fault_mmio,     "shadow_fault handled as mmio")
 PERFCOUNTER_CPU(shadow_fault_fixed,    "shadow_fault fixed fault")
 PERFCOUNTER_CPU(shadow_ptwr_emulate,   "shadow causes ptwr to emulate")